{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 90,
   "id": "9ed8c783-4b5b-423e-8020-a75ff1ce60c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d23b79c4-9b07-43c5-9a55-6097dcfd0c03",
   "metadata": {},
   "source": [
    "全量梯度下降和随机梯度下降的折中  \n",
    "每次迭代的数据量比1大，比m小，m是数据总行数  \n",
    "直线 曲线  折线的类似   \n",
    "兼顾单次计算量和总计算次数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "id": "fee2ed8f-abed-4217-b3dc-0a2b50e782c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "x=2*np.random.rand(100,1)\n",
    "y=4+3*x+np.random.randn(100,1)\n",
    "x_b=np.c_[np.ones((100,1)),x]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "id": "6ae59d5d-c073-400b-886e-2f8cd910ca78",
   "metadata": {},
   "outputs": [],
   "source": [
    "n_epochs=10000\n",
    "m=100\n",
    "batch_size=10\n",
    "n_batchs=int(m/batch_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "id": "5fad349b-5cfb-4157-b118-fea73d83365e",
   "metadata": {},
   "outputs": [],
   "source": [
    "theta=np.random.randn(2,1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "834263f2-1c50-4753-a68e-e913f0322c07",
   "metadata": {},
   "source": [
    "2行10列 点乘 （（10行2列点乘2行1列）-10行1列）  结果2行1列  \n",
    "这里index+batch_size不用处理越界错误，系统会自己搞定"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "37aa4a19-4f22-4ec5-8a9d-892fb11df44c",
   "metadata": {},
   "outputs": [],
   "source": [
    "t0,t1=1,200\n",
    "def learning_rate_adjust(t):\n",
    "    return t0/(t+t1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "0893aa47-e91f-4d43-b9fc-65a42c2891e5",
   "metadata": {},
   "outputs": [],
   "source": [
    "for t in range(n_epochs):\n",
    "    shuffled_indices = np.random.permutation(m)\n",
    "    x_shuffled = x_b[shuffled_indices]\n",
    "    y_shuffled = y[shuffled_indices]\n",
    "    for i in range(n_batchs):\n",
    "        start = i * batch_size\n",
    "        end = start + batch_size\n",
    "        x_batch = x_shuffled[start:end]\n",
    "        y_batch = y_shuffled[start:end]\n",
    "        learning_rate=learning_rate_adjust(t+i)\n",
    "        gradients=x_batch.T.dot(x_batch.dot(theta)-y_batch)\n",
    "        theta=theta-learning_rate*gradients"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e192831-d281-486d-8e82-9a5c8e570305",
   "metadata": {},
   "source": [
    "使用np.random.permutation打乱数据顺序确保均匀采样  \n",
    "x_shuffled = x_b[shuffled_indices]  让x_shuffled中的数据是x_b中的乱序备份   \n",
    "i在0到9之中取，可按固定步长 start 和 end 划分 batch，避免索引越界，且均匀访问乱序矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "15bef68c-f48c-42e4-a620-ffaf1b65d9e3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3.96294278]\n",
      " [3.17504602]]\n"
     ]
    }
   ],
   "source": [
    "print(theta)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc68005b-e604-474f-9ff5-6237ebc5a4ec",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
